# !/usr/bin/env python
# -*- coding:utf-8 -*-
# @FileName  :users.py
# @Time      :2022/5/27 0027 14:48
# @Author    :何胜利
import random

import redis
from flask import Blueprint, jsonify, g
from flask_restful import Api, Resource, reqparse, marshal
from sqlalchemy import and_
from werkzeug.security import generate_password_hash

from common.model_fields.user import followList_fields, comments_fields
from common.tasks.send_code import sms_code
from common.utils.jwt_util import _generate_token
from common.utils.login_utils import login_required
from common.utils.qiniu_files import qiniu_token
from common.utils.user_cache import UserCache
from models import db
from models.user import UserModel, Relation, Comment, UserChannel

user_bp = Blueprint("user_bp", __name__, url_prefix="/users")

api = Api(user_bp)


# 注册蓝图
class RegisterResource(Resource):
    def post(self):
        parser = reqparse.RequestParser()
        parser.add_argument("username")
        parser.add_argument("password")
        parser.add_argument("nickname")
        parser.add_argument("mobile")
        parser.add_argument("confirmpassword")
        args = parser.parse_args()
        uname = args["username"]
        pwd = args["password"]
        nick_name = args["nickname"]
        mobile = args["mobile"]
        confirm_pwd = args["confirmpassword"]

        if len(uname) > 32:
            return jsonify(message="账号太长", code=400)
        if pwd != confirm_pwd:
            return jsonify(message="两次密码不一样", code=400)
        try:
            UserModel.query.filter_by(mobile=mobile).first()
        except Exception as e:
            print("错误原因是>>>", e)
            return jsonify(message="手机号已存在", code=400)

        hash_pwd = generate_password_hash(pwd)
        try:
            user = UserModel(mobile=mobile, account=uname, password=hash_pwd, user_name=nick_name)
            db.session.add(user)
            db.session.commit()
        except Exception as e:
            print("register error", e)
            return jsonify(message="注册失败", code=400)
        return jsonify(messags="注册成功", code=200)


# 发送短信验证码
class SendSmdCode(Resource):
    def post(self):
        parser = reqparse.RequestParser()
        parser.add_argument("mobile")
        args = parser.parse_args()
        mobile = args["mobile"]
        print("前端输入的手机号", mobile)

        # 生成验证码
        code = random.randint(1000, 9999)

        # 发送验证码
        res = sms_code.delay(mobile, code)

        if res:
            # 发送成功，把验证码存在redis里
            rdb = redis.Redis(db=2)
            rdb.set(mobile, code, ex=600)
            rdb.close()
            return jsonify(message="短信发送成功！", code=200)
        else:
            return jsonify(message="短信发送失败！", code=500)


# 登录
class LoginResource(Resource):
    # 登录
    def post(self):
        # 获取前端数据
        parser = reqparse.RequestParser()
        parser.add_argument("mobile")
        parser.add_argument("sms")
        args = parser.parse_args()
        mobile = args["mobile"]
        sms = args["sms"]

        # 判断验证码是否正确
        rdb = redis.Redis(db=2)
        sms_code = rdb.get(mobile)
        print("redis里面的验证码：", sms_code)
        # 判断
        if sms != sms_code.decode('utf-8'):
            return jsonify(message="验证码错误", code=400)

        try:
            # 查询用户
            user = UserModel.query.filter_by(mobile=mobile).first()
        except Exception as e:
            print(e)
            return jsonify(messaga="此手机号未注册", code=400)

        # 用户不存在
        user_id = user.uid
        token, refresh_token = _generate_token(user_id)
        print("token>>>>", token)
        print("refresh_token>>>>", refresh_token)
        if token:
            return jsonify(messags="登录成功", code=200,
                           data={"token": token, "user_id": user_id, "refresh_token": refresh_token})
        else:
            return jsonify(messags="生成token失败", code=400)


# 获取用户信息
class UserInfo(Resource):
    def get(self, id):
        """根据用户id 获取用户信息"""
        # user = UserModel.query.filter_by(uid=id).first()

        # 把用户信息从mysql中获取变成从redis缓存中获取
        user = UserCache(id).get()
        print("缓存的用户信息", user)
        # if user:
        # user1 = marshal(user, user_fields)
        print("返回的用户信息", user)
        return jsonify(data=user)


# 关注
class RelationResource(Resource):
    @login_required
    def get(self):
        uid = g.user_id
        if uid:
            user = Relation.query.filter_by(user_id=uid).all()
            # print("关注表user----->", user)
            user_list = [UserModel.query.filter_by(uid=i.foller_id).first() for i in user]
            followList = marshal(user_list, followList_fields)
            # print('followList----', followList)
            return followList


# 修改密码
class UserPwdUpdate(Resource):
    def post(self, id):
        uid = g.user_id
        parser = reqparse.RequestParser()
        parser.add_argument("password")
        parser.add_argument("user_name")
        parser.add_argument("gender")
        parser.add_argument("img")
        args = parser.parse_args()
        user_name = args["user_name"]
        pwd = args["password"]
        gender = args["gender"]
        img = args["img"]
        # 修改昵称
        if user_name:
            UserModel.query.filter_by(uid=g.user_id).update({"user_name": user_name})
            db.session.commit()
            return jsonify(message="修改昵称成功", code=200)

        # 修改密码
        if pwd:
            hash_pwd = generate_password_hash(pwd)
            UserModel.query.filter_by(uid=uid).update({"password": hash_pwd})
            db.session.commit()
            data_ = {
                "id": g.user_id
            }
            token, refresh_token = _generate_token(data_)
            rdb = redis.Redis(db=8)
            rdb.set("user:%s:token"%g.user_id, token, 2*60*60)
            return jsonify(message="修改密码成功", code=200,
                           data={"token": token, "id": g.user_id, "refresh_token": refresh_token})

        # 修改性别
        if gender:
            UserModel.query.filter_by(uid=g.user_id).update({"gender": gender})
            db.session.commit()
            return jsonify(message="修改性别成功", code=200)

        # 修改头像
        if img:
            UserModel.query.filter_by(uid=g.user_id).update({"profile_photo": img})
            db.session.commit()
            return jsonify(message="修改头像成功", code=200)


# 跟帖
class CommentsResource(Resource):
    @login_required
    def get(self):
        comments = Comment.query.all()
        # print("comments----->", comments)
        comment = marshal(comments, comments_fields)
        return comment


# 取消频道关注
class ChannelCancelResource(Resource):
    def get(self, id):
        uid = g.user_id
        if uid:
            user = UserModel.query.filter_by(uid=uid).first()
            UserChannel.query.filter(and_(UserChannel.uid == user.uid, UserChannel.cid == id)).delete()
            db.session.commit()
            return jsonify(message="取消成功", code=200)
        else:
            return jsonify(message="取消失败", code=400)


# 取消我的关注的关注
class FollowsCancelResource(Resource):
    def get(self, id):
        uid = g.user_id
        if uid:
            user = UserModel.query.filter_by(uid=uid).first()
            Relation.query.filter(and_(Relation.user_id == user.uid, Relation.foller_id == id)).delete()
            db.session.commit()
            return jsonify(message="取消成功", code=200)
        else:
            return jsonify(message="取消失败", code=400)


# 生成七牛云上传的
class QiniuTokenResource(Resource):
    @login_required
    def get(self):
        token = qiniu_token()
        print("七牛云的token", token)
        return jsonify(message="ok", code=200, data={"token": token})


api.add_resource(QiniuTokenResource, "/qiniu_token")
api.add_resource(FollowsCancelResource, "/user_unfollow/<int:id>")
api.add_resource(ChannelCancelResource, "/user_channels/<int:id>")
api.add_resource(CommentsResource, "/user_comments")
api.add_resource(UserPwdUpdate, "/user_update/<int:id>")
api.add_resource(RelationResource, "/follows")
api.add_resource(UserInfo, "/info/<int:id>")
api.add_resource(LoginResource, "/login")
api.add_resource(SendSmdCode, "/sms_code")
api.add_resource(RegisterResource, "/register")
